package xcore

import (
	"context"
	"gitee.com/go-mid/infra/xlog"
	"math/rand"
	"strconv"
	"strings"
	"unicode"
)

func SplitToInt64(ctx context.Context, s, sep string, distinct bool) []int64 {
	split := SplitAndTrim(ctx, s, sep, distinct)
	items := make([]int64, 0, len(split))
	for _, str := range split {
		i, err := strconv.ParseInt(strings.TrimSpace(str), 10, 64)
		if err != nil {
			xlog.Infof(ctx, "parse int err: s:%s, err:%v", str, err)
			continue
		}
		items = append(items, i)
	}
	return items
}
func SplitAndTrim(ctx context.Context, s, sep string, distinct bool) []string {
	split := strings.Split(s, sep)
	items := make([]string, 0, len(split))
	var dismap map[string]struct{}
	if distinct {
		dismap = make(map[string]struct{}, len(split))
	}
	for _, str := range split {
		str = strings.TrimSpace(str)
		if distinct {
			_, ok := dismap[str]
			if ok {
				continue
			}
			dismap[str] = struct{}{}
		}
		items = append(items, str)
	}
	return items
}

//是否命中
//rate是比例，比如 50%，此处是50
// 判断v的尾号2位是否小于登录rate
// n n表示取尾数几位
func IsHitRateInt(ctx context.Context, n int, rate int, v int64) bool {
	var base int64 = 1
	for i := 0; i < n; i++ {
		base *= 10
	}
	if rate > 0 {
		lowvalue := int(v % base)
		if lowvalue < rate {
			return true
		}
	}
	return false
}

func InWhiteList(ctx context.Context, s, sep string, v int64) bool {
	split := strings.Split(s, sep)
	for _, str := range split {
		str = strings.TrimSpace(str)
		i, err := strconv.ParseInt(strings.TrimSpace(str), 10, 64)
		if err != nil {
			xlog.Infof(ctx, "parse int err: s:%s, err:%v", str, err)
			continue
		}
		if v == i {
			return true
		}
	}
	return false
}
func InWhiteListString(ctx context.Context, s, sep string, v string) bool {
	split := strings.Split(s, sep)
	for _, str := range split {
		if strings.TrimSpace(v) == strings.TrimSpace(str) {
			return true
		}
	}
	return false
}
func InWhiteListV2(ctx context.Context, s, sep string, v int64, starIsAll bool) bool {
	split := strings.Split(s, sep)
	for _, str := range split {
		str = strings.TrimSpace(str)
		if starIsAll && str == "*" {
			return true
		}
		i, err := strconv.ParseInt(strings.TrimSpace(str), 10, 64)
		if err != nil {
			xlog.Infof(ctx, "parse int err: s:%s, err:%v", str, err)
			continue
		}
		if v == i {
			return true
		}
	}
	return false
}
func InWhiteListStringV2(ctx context.Context, s, sep string, v string, starIsAll bool) bool {
	split := strings.Split(s, sep)
	for _, str := range split {
		str = strings.TrimSpace(str)
		if starIsAll && str == "*" {
			return true
		}
		if strings.TrimSpace(v) == str {
			return true
		}
	}
	return false
}

func JoinIntSlice(ctx context.Context, vs []int, sep string) string {
	return strings.Join(IntSliceToStrSlice(ctx, vs), sep)
}
func JoinInt64Slice(ctx context.Context, vs []int64, sep string) string {
	return strings.Join(Int64SliceToStrSlice(ctx, vs), sep)
}
func IntSliceToStrSlice(ctx context.Context, vs []int) []string {
	var vsStrArra = make([]string, 0, len(vs))
	for _, v := range vs {
		vsStrArra = append(vsStrArra, strconv.Itoa(v))
	}
	return vsStrArra
}
func Int64SliceToStrSlice(ctx context.Context, vs []int64) []string {
	var vsStrArra = make([]string, 0, len(vs))
	for _, v := range vs {
		vsStrArra = append(vsStrArra, strconv.Itoa(int(v)))
	}
	return vsStrArra
}
func StrSliceToInt64Slice(ctx context.Context, vs []string) []int64 {
	var vsInt64Arra = make([]int64, 0, len(vs))
	for _, v := range vs {
		vint64, err := strconv.ParseInt(v, 10, 64)
		if err != nil {
			xlog.Infof(ctx, "parse str to int64 error: v:%s, err:%v", v, err)
			continue
		}
		vsInt64Arra = append(vsInt64Arra, vint64)
	}
	return vsInt64Arra
}

func HasArrayElement(haystack string, needles []string, caseSensitive bool) (string, bool) {
	for _, v := range needles {
		if !caseSensitive {
			haystack = strings.ToUpper(haystack)
			v = strings.ToUpper(v)
		}

		if strings.Contains(haystack, v) {
			return v, true
		}
	}

	return "", false
}

func Int64SliceToInterfaceSlice(ctx context.Context, vs []int64) []interface{} {
	var vsStrArra = make([]interface{}, 0, len(vs))
	for _, v := range vs {
		vsStrArra = append(vsStrArra, v)
	}
	return vsStrArra
}

func Int32SliceToInterfaceSlice(ctx context.Context, vs []int32) []interface{} {
	var vsStrArra = make([]interface{}, 0, len(vs))
	for _, v := range vs {
		vsStrArra = append(vsStrArra, v)
	}
	return vsStrArra
}

func IntSliceToInterfaceSlice(ctx context.Context, vs []int) []interface{} {
	var vsStrArra = make([]interface{}, 0, len(vs))
	for _, v := range vs {
		vsStrArra = append(vsStrArra, v)
	}
	return vsStrArra
}
func StrSliceToInterfaceSlice(ctx context.Context, vs []string) []interface{} {
	var vsStrArra = make([]interface{}, 0, len(vs))
	for _, v := range vs {
		vsStrArra = append(vsStrArra, v)
	}
	return vsStrArra
}

func IntSlice2Int64Slice(s []int) []int64 {
	var r []int64
	for _, i := range s {
		r = append(r, int64(i))
	}
	return r
}
func IntSlice2Int32Slice(s []int) []int32 {
	var r []int32
	for _, i := range s {
		r = append(r, int32(i))
	}
	return r
}
func JsonString(ctx context.Context, obj interface{}) string {
	data, err := MarshalJSON(obj)
	if err != nil {
		xlog.Warnf(ctx, "marshal error : obj: %v, err: %v", obj, err)
		return ""
	}
	return string(data)
}
func RandomShuffling(ctx context.Context, v string) string {
	if len(v) <= 0 {
		return ""
	}
	var rs = []rune(v)
	for i := 0; i < len(rs); i++ {
		var randIndex = rand.Intn(len(rs))
		rs[i], rs[randIndex] = rs[randIndex], rs[i]
	}
	return string(rs)
}

//下划线单词转为大写驼峰单词
// eddycjy --> Eddycjy
func UderscoreToUpperCamelCase(s string) string {
	s = strings.Replace(s, "_", " ", -1)
	s = strings.Title(s)
	return strings.Replace(s, " ", "", -1)
}

//下划线单词转为小写驼峰单词
//EDDYCJY --> eDDYCJY
func UderscoreToLowerCamelCase(s string) string {
	s = UderscoreToUpperCamelCase(s)
	return string(unicode.ToLower(rune(s[0]))) + s[1:]
	return s
}

//驼峰单词转下划线单词
//EddyCjy --> eddy_cjy
func CamelCaseToUdnderscore(s string) string {
	return CamelCaseToSep(s, "_")
}
func CamelCaseToSep(s string, sep string) string {
	var output []rune
	for i, r := range s {
		if i == 0 {
			output = append(output, unicode.ToLower(r))
		} else {
			if unicode.IsUpper(r) {
				output = append(output, []rune(sep)...)
			}

			output = append(output, unicode.ToLower(r))
		}
	}
	return string(output)
}
